home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr31 / arcv122.zip / ARCV122.ASM next >
Assembly Source File  |  1993-05-26  |  27KB  |  1,197 lines

  1.     page    80,132
  2.     title    ARCV - Verbose ARC directory listing
  3.  
  4. ; usage:
  5. ;    arcv [d:\path\]filespec[.arc] [/p] [/z]
  6. ;
  7. ; history:
  8. ;    version 1.00 - 1/5/86
  9. ;    version 1.03 - 1/10/86
  10. ;        released for general use
  11. ;    version 1.04 - 1/19/86
  12. ;        make displays MS-DOS compatible
  13. ;    version 1.05 - 1/23/86
  14. ;        supports ARC 5.0 new formats
  15. ;    version 1.06 - 1/26/86
  16. ;        correct total SF
  17. ;    version 1.07 - 3/22/86
  18. ;        change open for input only
  19. ;    version 1.08 - 3/28/86
  20. ;        correct zero divide problem
  21. ;    version 1.09 - 4/08/86
  22. ;        check SF for funny archives
  23. ;    version 1.10 - 4/18/86
  24. ;        correct divide overflow problem
  25. ;    version 1.11 - 4/23/86
  26. ;        correct stowage factor
  27. ;    version 1.12 - 4/26/86
  28. ;        correct sending totals for no files
  29. ;    version 1.13 - 5/11/86
  30. ;        expand search for header arcmark
  31. ;    version 1.14 - 5/21/86
  32. ;        change for 'No files found' error on clones
  33. ;    version 1.15 - 6/14/86
  34. ;        use 'filename' if no files found to use DPATH
  35. ;    version 1.16 - 12/31/86
  36. ;        add entry for type 9 format, squashing
  37. ;    version 1.17 - 1/27/86
  38. ;        add DOS 3.x file sharing
  39. ;    version 1.18 - 1/11/89
  40. ;        add crushing method used by GSARC
  41. ;        add pause option
  42. ;        correct problem with zero time
  43. ;    version 1.19 - 2/06/89
  44. ;        add display of new ARC 6.00 items
  45. ;    version 1.20 - 2/09/89
  46. ;        cosmetic changes; fix-up jumps for MASM
  47. ;    version 1.21 - 3/06/89
  48. ;        added /B parameter to suppress d:\path for BBS use
  49. ;    version 1.22 - 4/12/91
  50. ;        added recognition of info records for ARC v7
  51.  
  52.     .xlist
  53. print    macro    name            ; display a field
  54.     mov    dx,offset name
  55.     call    prints
  56.     endm
  57.  
  58. printl    macro    text            ; display a literal
  59.     local    txt,nxt
  60.     mov    dx,offset txt
  61.     call    prints
  62.     jmp    nxt
  63. txt    db    cr,lf,text
  64.     db    stopper
  65. nxt    equ    $
  66.     endm
  67.  
  68. beep    macro                ; sound the horn
  69.     mov    dl,7
  70.     mov    ah,2
  71.     int    21h
  72.     endm
  73.  
  74. save    macro    reglist
  75.     irp    reg, <reglist>
  76.     push    reg
  77.     endm
  78.     endm
  79.  
  80. restore macro    reglist
  81.     irp    reg, <reglist>
  82.     pop    reg
  83.     endm
  84.     endm
  85.     .list
  86.  
  87. header    struc                ; archive header
  88. mbrcode db    0            ;  compression code
  89. mbrname db    13 dup (0)        ;  file name
  90. mbrsize dw    0,0            ;  file size in archive
  91. mbrdate dw    0            ;  creation date
  92. mbrtime dw    0            ;  creation time
  93. mbrcrc    dw    0            ;  cyclic redunancy check
  94. mbrlen    dw    0,0            ;  true file size, bytes
  95. header    ends
  96.  
  97.  
  98. cseg    segment public para 'CODE'
  99.     assume    cs:cseg,ds:cseg,es:cseg
  100.     org    100h
  101.  
  102. arcv    proc    far
  103.     mov    stkptr,sp        ; save stack ptr
  104.     mov    ah,30h            ; get dos version
  105.     int    21h
  106.     mov    dosver,al        ; save for open checks
  107.     cmp    al,2            ; version 2 or later?
  108.     jb    badver            ; no, gotta quit
  109.     jmp    start            ; do our thing
  110.  
  111. ;    return with error
  112.  
  113. badver: print    vermsg            ; version 2 red'q
  114. error:    mov    ax,cs            ; insure seg regs
  115.     mov    ds,ax            ;  for proper exit
  116.     mov    sp,cs:stkptr
  117.     mov    errlvl,1        ; set bad return code
  118.     beep
  119.     jmp    arcv2a            ; produce totals anyway
  120.  
  121. ;    set DOS error level and exit
  122.  
  123. exit:    mov    sp,cs:stkptr        ; just in case
  124.     mov    al,errlvl        ; return code
  125.     mov    ah,4ch            ; exit function
  126.     int    21h
  127.  
  128.     subttl    '--- constants, equates and work areas'
  129.     page
  130.  
  131. cr    equ    13
  132. lf    equ    10
  133. bel    equ    7
  134. tab    equ    9
  135.  
  136. arcver    equ    39        ; highest compression code or item used
  137.                 ;     0 = end of archive marker
  138.                 ;  1-19 = standard compressed file
  139. infotype    equ    20    ; 20-29 = information items
  140. controltype    equ    30    ; 30-39 = control items
  141.  
  142. stkptr    dw    0        ; stack pointer upon entry
  143. stopper equ    0        ; end of display line indicator
  144.  
  145. arcmark equ    26        ; special archive marker
  146. errlvl    db    0        ; dos error level returned
  147. flags    db    0        ; find-first return code
  148. dosver    db    0        ; major dos version
  149.  
  150. options db    0        ; command line options
  151. p_parm    equ    1        ; /p used to pause
  152. z_parm    equ    2        ; /z used for verbose subdir listing
  153. b_parm    equ    4        ; /b used to suppress d:\path display
  154.  
  155. archdl    dw    0        ; file handle
  156.  
  157. arctitl db    cr,lf,'Archive:  ',stopper
  158.  
  159. arcfile db    13 dup (0),0,stopper
  160.  
  161. arcname db    '*',0,74 dup (stopper)
  162.  
  163. fileptr dw    0        ; ptr to filename part of arcname
  164.  
  165.     subttl    '--- i/o control variables'
  166.     page
  167.  
  168. usage    db    cr,lf,     'ARCV Version 1.22 Copyright (c) 1991 Vernon D. Buerg'
  169.     db    cr,lf,     'For personal use only. May not be sold.'
  170.     db    cr,lf,lf,'  Usage:  arcv [d:][\path\]filespec[.ARC]  [/p][/z][/b]'
  171.     db    cr,lf,stopper
  172.  
  173. inbufsz equ    30        ; size of input buffer, seems best
  174. inadr    dw    offset inbuf    ; offset to input buffer
  175. inptr    dw    offset inbuf    ; offset to current byte
  176. insize    dw    inbufsz     ; size of input buffer
  177. inlen    dw    0        ; bytes left in buffer
  178.  
  179. ;    display lines for verbose
  180.  
  181. vhdr    db    cr,lf
  182.     db    cr,lf,'Name          Length    Stowage    SF   Size now  Date       Time    CRC '
  183.     db    cr,lf,'============  ========  ========  ====  ========  =========  ======  ===='
  184.     db    stopper
  185.  
  186. vline    db    cr,lf
  187. vname    db    14 dup (' ')
  188. vlength db    '       0  '    ; length in archive
  189. vstyle    db    '          '    ; compression method
  190. vfactor db    ' xx%  '        ; compression factor
  191. vsize    db    10 dup (' ')    ; actual file bytes
  192. vdate    db    'dd '           ; creation date
  193.  vmonth db    'mmm '
  194.  vyear    db    'yy  '
  195.  vtime    db    'hh:mm   '      ; creation time
  196.  vcrc    db    'xxxx'          ; crc in hex
  197.     db    stopper
  198.  
  199. totsf    dw    0,0        ; average stowage factor
  200. totlen    dw    0,0        ; total of file lengths
  201. totsize dw    0,0        ; total of file sizes
  202. totmbrs dw    0        ; total number of files
  203.  
  204. ;    final totals line
  205.  
  206. vthdr    db    cr,lf,'*total    '
  207.  vtmbrs db    '    '
  208.  vtlen    db    8 dup (' '),'  '
  209.     db    10 dup (' ')
  210.  vtsf    db    '   %  '
  211.  vtsize db    8 dup (' ')
  212.     db    cr,lf        ; for tom
  213.     db    stopper
  214.  sign    db    ' '
  215.  
  216. styles    db    '  ----- '      ;  1 = old, no compression
  217.     db    '  ----- '      ;  2 = new, no compression
  218.     db    ' Packed '      ;  3 = dle for repeat chars
  219.     db    'Squeezed'      ;  4 = huffman encoding
  220.     db    'crunched'      ;  5 = lz, no dle
  221.     db    'crunched'      ;  6 = lz with dle
  222.     db    'Crunched'      ;  7 = lz with readjust
  223.     db    'Crunched'      ;  8 = lz with readjust and dle
  224.     db    'Squashed'      ;  9 = modified lzw, no dle
  225.     db    'Crushed '      ; 10 = GSARC/PAK modified LZW
  226.     db    'unknown '      ; 11 = reserved
  227.     db    'unknown '      ; 12 = reserved
  228.     db    'unknown '      ; 13 = reserved
  229.     db    'unknown '      ; 14 = reserved
  230.     db    'unknown '      ; 15 = reserved
  231.     db    'unknown '      ; 16 = reserved
  232.     db    'unknown '      ; 17 = reserved
  233.     db    'unknown '      ; 18 = reserved
  234.     db    'unknown '      ; 19 = reserved
  235.  
  236. hundred dw    100        ; for computing percentages
  237. months    db    'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec '
  238.  
  239.     subttl    '--- mainline processing'
  240.     page
  241. ;
  242. ;    determine if command line or menu driven mode
  243.  
  244. start:
  245.     mov    si,82h            ; Command tail
  246.     sub    cx,cx            ;
  247.     or    cl,byte ptr -2[si]    ; test parm length
  248.     jz    getparms        ; none, return as-is
  249.  
  250. sw1:    lodsb                ; scan for switch
  251.     cmp    al,'/'                  ;
  252.     loopne    sw1            ;
  253.     or    cx,cx            ; found one?
  254.     jz    getparms        ; no, done
  255.     mov    byte ptr -1[si],cr    ; yes, stop command line there
  256.     jmp    sw2a            ; and check next character
  257.  
  258. sw2:    lodsb                ; Next character
  259.     cmp    al,'/'                  ; Another switch?
  260.     loopne    sw2            ;
  261.     jcxz    getparms        ;
  262.  
  263. sw2a:    lodsb                ; yes, get letter following
  264.     and    al,0dfh         ; make upper case
  265.     dec    cx            ;
  266.     jle    sw3            ; missing switch
  267.  
  268. sw3:    cmp    al,'P'                  ; Pause?
  269.     jne    sw4            ;
  270.     or    options,p_parm        ;
  271.  
  272. sw4:    cmp    al,'Z'                  ; Expand subdir?
  273.     jne    sw5            ;
  274.     jne    sw2            ;
  275.     or    options,z_parm        ;
  276.  
  277. sw5:    cmp    al,'B'                  ; BBS use
  278.     jne    sw2            ;
  279.     or    options,b_parm        ;
  280.     jmp    sw2            ; Try for another option
  281.  
  282.     subttl    --- Gather command operands
  283.     page
  284.  
  285. ;    copy first command line operand
  286.  
  287. getparms:
  288.     mov    si,80h            ; offset to command line
  289.     sub    cx,cx            ; its length
  290.     or    cl,byte ptr [si]    ; any operand?
  291.     jnz    parm0            ; no,
  292.     print    usage            ;  display usage
  293.     jmp    exit            ;   and quit
  294.  
  295. parm0:    inc    si            ; point to operands
  296. parm2:    lodsb                ; strip leading blanks
  297.     cmp    al,' '                  ;
  298.     loope    parm2            ;
  299.  
  300.     mov    di,offset arcname    ; first operand target
  301.     stosb                ;
  302. parm3:    lodsb                ; copy filename
  303.     cmp    al,cr            ; end of name?
  304.     je    parm4            ;
  305.     cmp    al,' '                  ; don't know why this is here
  306.     je    parm4            ;
  307.     stosb                ;
  308.     loop    parm3            ;
  309. parm4:
  310.     mov    si,offset arcname+75    ; end of filename stuff
  311.     std                ;
  312.     mov    cl,76            ; search for last path
  313. parm5:
  314.     lodsb                ;
  315.     cmp    al,'/'                  ; funny path delimiter?
  316.     je    parm6            ;
  317.     cmp    al,'\'                  ; normal path delimiter?
  318.     je    parm6            ;
  319.     cmp    al,':'                  ; bumped into drive?
  320.     je    parm6            ;
  321.     loop    parm5            ;
  322.     dec    si            ;
  323. parm6:
  324.     cld                ;
  325.     add    si,2            ; point to where filename goes
  326.     mov    fileptr,si        ; and save for later
  327.  
  328. ;    add default ARC extension if necessary
  329.  
  330.     mov    si,fileptr        ; start of filespec
  331.     mov    cx,13            ;
  332. parm10:
  333.     lodsb
  334.     cmp    al,0            ; end of name?
  335.     je    parm11            ;
  336.     cmp    al,'.'                  ; got extension?
  337.     je    parm12            ;
  338.     loop    parm10            ;
  339. parm11:
  340.     mov    di,si            ; ptr to end of name
  341.     dec    di            ;
  342.     mov    ax,'A.'                 ; default extension
  343.     stosw                ;
  344.     mov    ax,'CR'                 ;
  345.     stosw                ;
  346.     mov    ax,0FF00h        ; append stoppers
  347.     stosw                ;
  348. parm12:
  349.  
  350.     subttl    - Find matching files
  351.     page
  352.  
  353. ;    find first matching file
  354.  
  355. getfirst:
  356.     mov    dx,offset dta        ; set local dta for murkers
  357.     mov    ah,1ah            ;
  358.     int    21h            ;
  359.  
  360.     mov    dx,offset arcname    ; find first matching file
  361.     sub    cx,cx            ; normal attribute
  362.     mov    ah,4eh            ;
  363.     int    21h            ;
  364.     mov    flags,al        ; indicate find-first status
  365.     or    ax,ax            ; any return code?
  366.     jz    parm7            ;
  367.     jmp    not_found        ; in case of DPATH utility
  368. nofiles:
  369.     printl    'No file(s) found'      ;
  370.     jmp    error            ;
  371.  
  372. getnext:
  373.     mov    ah,4fh            ; get next file name
  374.     int    21h            ;
  375.     jc    alldone         ;
  376.     or    ax,ax            ;
  377.     jz    parm7            ;
  378. alldone:
  379.     jmp    exit            ;
  380.  
  381. ;    set up next matching file name
  382.  
  383. parm7:
  384.     mov    si,offset dta+30    ; point to filename found
  385.     mov    di,fileptr        ; and overlay old name
  386.     mov    cx,13            ;
  387.     rep    movsb            ;
  388.  
  389.     mov    si,offset dta+30    ; copy filename for heading
  390.     mov    di,offset arcfile    ;
  391.     mov    cx,13            ; asciiz filename
  392.     rep    movsb            ;
  393.     mov    al,stopper        ; +stopper
  394.     stosb                ;
  395.  
  396. ;    re-initialize
  397.  
  398. not_found:
  399.     sub    ax,ax            ; reset totals counters
  400.     mov    totmbrs,ax        ;
  401.     mov    totsize,ax        ;
  402.     mov    totsize+2,ax        ;
  403.     mov    totlen,ax        ;
  404.     mov    totlen+2,ax        ;
  405.     mov    totsf,ax        ;
  406.     mov    inlen,ax        ;
  407.     mov    dx,offset inbuf     ;
  408.     mov    inptr,dx        ;
  409.  
  410.     call    openarc         ; see if archive exists
  411.     jnc    arcv1            ;
  412.     ret                ;
  413.  
  414.     subttl    - Process archive headers
  415.     page
  416. ;
  417. ;    process next archive header entry
  418.  
  419. arcv1: ;inc    linecnt         ; get all on one page
  420.     print    arctitl         ;
  421.     test    options,b_parm        ; full d:\path name?
  422.     jnz    arcv1a            ;  no
  423.     print    arcname         ;
  424.     jmp    arcv1b            ;
  425.  
  426. arcv1a: print    arcfile         ;
  427. arcv1b: print    vhdr            ;
  428.  
  429. arcvnext:
  430.     call    gethdr            ; load next header
  431.     jnc    arcv2            ;
  432.     jmp    exit            ; all done
  433.  
  434. arcv2:    cmp    archdr.mbrcode,0    ; archive eof?
  435.     je    arcv2a            ; yes, all done
  436.     jmp    arcvgo            ;
  437.  
  438. arcv2a:
  439.     mov    ax,totmbrs        ; total files
  440.     or    ax,ax            ; are there any?
  441.     jnz    format_totals        ;
  442.     jmp    skip_totals        ;
  443.  
  444. format_totals:
  445.     sub    dx,dx            ;
  446.     mov    si,offset vtmbrs-4    ;
  447.     call    format            ;
  448.  
  449.     mov    dx,totlen+2        ; total actual file size
  450.     mov    ax,totlen        ;
  451.     mov    si,offset vtlen     ;
  452.     call    format            ;
  453.  
  454.     mov    dx,totsize+2        ; total achive file size
  455.     mov    ax,totsize        ;
  456.     mov    si,offset vtsize    ;
  457.     call    format            ;
  458.  
  459. ; reduce the total size/length to word values
  460.  
  461.     mov    bx,totlen        ; get actual file size
  462.     mov    ax,totlen+2        ;
  463.     mov    cx,totsize        ; length of file in archive
  464.     mov    dx,totsize+2        ;
  465. arcv2b: or    ax,ax            ; big number?
  466.     jz    arcv2c            ; nope, can use it
  467.     shr    ax,1            ; yup, divide by two
  468.     rcr    bx,1            ;
  469.     shr    dx,1            ;
  470.     rcr    cx,1            ;
  471.     jmp    arcv2b            ;
  472.  
  473. arcv2c: mov    si,offset vtsf-5    ; format stowage factor
  474.     mov    ax,bx
  475.     mov    sign,' '                ; whata kludge
  476.     cmp    ax,cx            ; arc is bigger than orig?
  477.     jb    arcv2c1
  478.     sub    ax,cx            ; amount saved
  479.     jmp    arcv2f            ;
  480. arcv2c1:
  481.     sub    ax,cx            ;
  482.     neg    ax            ;
  483.     mov    sign,'-'                ;
  484. arcv2f:
  485.     mul    hundred         ; to percentage
  486.     add    ax,50            ;
  487.     adc    dx,0            ; round up percent
  488.     or    bx,bx            ; empty file?
  489.     jnz    arcv2d            ;
  490.     mov    ax,100            ;
  491.     jmp    arcv2e            ;
  492.  
  493. arcv2d: div    bx            ;
  494. arcv2e: sub    dx,dx            ;
  495.     call    format            ;
  496.  
  497.     mov    al,sign         ;
  498.     mov    vtsf,al         ;
  499.     print    vthdr            ; display totals
  500.     inc    linecnt         ;
  501. skip_totals:
  502.     call    closarc         ;
  503.     jmp    getnext         ;
  504.  
  505.     page
  506. ;
  507. ;    format single line for each member
  508.  
  509. arcvgo:
  510.     mov    di,offset vname     ; copy file name
  511.     mov    si,offset archdr.mbrname
  512.     mov    cx,13            ;
  513. arcv3:
  514.     lodsb                ;
  515.     cmp    al,0            ; end of name?
  516.     je    arcv4            ;
  517.     stosb                ;
  518.     loop    arcv3            ;
  519.     jmp    arcv5            ;
  520. arcv4:
  521.     mov    al,' '                  ; pad with blanks
  522.     rep    stosb            ;
  523. arcv5:
  524.     sub    bx,bx            ; determine style
  525.     mov    bl,archdr.mbrcode    ;
  526.  
  527.     cmp    bl,controltype        ; control record?
  528.     jb    arcv5c            ;
  529.     jmp    controlrec        ;
  530.  
  531. arcv5c: cmp    bl,infotype        ; information record?
  532.     jb    arcv5i            ;
  533.     jmp    inforec         ;
  534.  
  535. arcv5i:
  536.     inc    totmbrs         ;
  537.  
  538. ; reduce the size/length to word values
  539.  
  540.     mov    bx,archdr.mbrlen    ; get actual file size
  541.     mov    ax,archdr.mbrlen+2    ;
  542.  
  543.     mov    cx,archdr.mbrsize    ; length of file in archive
  544.     mov    dx,archdr.mbrsize+2    ;
  545.  
  546. arcv51: or    ax,ax            ; big number?
  547.     jz    arcv52            ; nope, can use it
  548.     shr    ax,1            ; yup, divide by two
  549.     rcr    bx,1            ;
  550.     shr    dx,1            ;
  551.     rcr    cx,1            ;
  552.     jmp    arcv51            ;
  553.  
  554. arcv52: mov    si,offset vfactor-5    ; format stowage factor
  555.     mov    ax,bx            ; low word of actual size
  556.     mov    sign,' '                ;
  557.     cmp    ax,cx            ; arc member is larger?
  558.     jb    arcv520         ;
  559.     sub    ax,cx            ; amount saved
  560.     jmp    arcv56            ;
  561. arcv520:
  562.     sub    ax,cx            ;
  563.     neg    ax            ;
  564.     mov    sign,'-'                ;
  565. arcv56:
  566.     mul    hundred         ; to percentage
  567.     add    ax,50            ;
  568.     adc    dx,0            ; round up percent
  569.     or    bx,bx            ; empty file?
  570.     jnz    arcv53            ;
  571.     mov    ax,100            ;
  572.     jmp    arcv54            ;
  573.  
  574. arcv53: div    bx            ;
  575. arcv54: sub    dx,dx            ;
  576.     cmp    ax,100            ; archive fouled?
  577.     jbe    arcv55            ;
  578.     sub    ax,ax            ;
  579. arcv55:
  580.     call    format            ;
  581.     mov    al,sign         ;
  582.     mov    vfactor,al        ;
  583.  
  584.     sub    bx,bx            ; determine style
  585.     mov    bl,archdr.mbrcode    ;
  586.  
  587.     mov    cl,3            ; eight bytes each entry
  588.     shl    bx,cl            ;
  589.     lea    si,styles-8[bx]     ; get ptr to style name
  590.     mov    di,offset vstyle    ;
  591.     mov    cx,8            ;
  592.     rep    movsb            ;
  593.  
  594.     mov    si,offset vsize     ; format file size
  595.     mov    dx,archdr.mbrsize+2    ;
  596.     mov    ax,archdr.mbrsize    ;
  597.     add    totsize,ax        ;
  598.     adc    totsize+2,dx        ;
  599.     call    format            ;
  600.  
  601.     mov    si,offset vlength    ; format file length
  602.     mov    dx,archdr.mbrlen+2    ;
  603.     mov    ax,archdr.mbrlen    ;
  604.     add    totlen,ax        ;
  605.     adc    totlen+2,dx        ;
  606.     call    format            ;
  607.  
  608.     mov    ax,archdr.mbrdate    ; format file date
  609.     call    getdate         ;
  610.  
  611.     mov    ax,archdr.mbrtime    ; format file time
  612.     call    gettime         ;
  613.  
  614.     mov    ax,archdr.mbrcrc    ; format crc in hex
  615.     mov    di,offset vcrc        ;
  616.     call    cvh            ;
  617.  
  618.     print    vline            ; display this file info
  619.  
  620. arcv_next:
  621.     mov    cx,word ptr archdr.mbrsize+2
  622.     mov    dx,word ptr archdr.mbrsize
  623.     sub    dx,inlen        ; less bytes read/unprocessed
  624.     sbb    cx,0
  625.     mov    ax,4201h        ; skip over file data
  626.     mov    bx,archdl        ;
  627.     int    21h            ;
  628.     mov    inlen,0         ; reset read buffer
  629.     jmp    arcvnext        ;
  630.  
  631.     subttl    --- Information records
  632.     page
  633.  
  634. infocode db    0            ; information record(s) code
  635.  
  636. info20    db    cr,lf,'Archive Information: ',stopper
  637. info21    db    cr,lf,'File Information: ',stopper
  638. info22    db    cr,lf,'Operating System Information: ',stopper
  639.  
  640. info20name    label  word
  641.     dw    info20descr
  642.     dw    info20creator
  643.     dw    info20modifier
  644. info20descr    label    byte
  645.     db    cr,lf,'Archive description: ',cr,lf,stopper
  646. info20creator    label    byte
  647.     db    cr,lf,'Creator: ',cr,lf,stopper
  648. info20modifier    label    byte
  649.     db    cr,lf,'Modifier: ',cr,lf,stopper
  650.  
  651. inforec:
  652.  
  653.     mov    bl,archdr.mbrcode    ; get record code
  654.     sub    bh,bh            ;
  655.  
  656.     mov    dx,offset info20    ;
  657.     cmp    bl,20            ; archive information?
  658.     je    inforec20        ;
  659.  
  660.     mov    dx,offset info21    ;
  661.     cmp    bl,21            ; file information?
  662.     je    inforec21        ;
  663.  
  664.     mov    dx,offset info22    ;
  665.     cmp    bl,22            ; operating system information?
  666.     je    inforec22        ;
  667.  
  668.     mov    dx,offset control30    ;
  669.     cmp    bl,30            ; subdirectory entry?
  670.     je    control30        ;
  671.  
  672.     mov    dx,offset control31    ;
  673.     cmp    bl,31            ; end of subdirectory?
  674.     je    control31        ;
  675.  
  676.     mov    di,offset hdrcode    ; display record type
  677.     mov    ax,bx            ;
  678.     call    cnvrt            ;
  679.     mov    word ptr hdrcode,ax    ; store record type
  680.     print    hdrmsg            ;
  681.     jmp    arcvnext        ;
  682.  
  683. control31:                ; end of subdirectory
  684.     jmp    arcvnext        ;
  685.  
  686. inforec21:
  687.     call    prints            ; display record name
  688.     jmp    arcvnext        ;
  689.  
  690. inforec22:
  691.     call    prints            ; display record name
  692.     jmp    arcvnext        ;
  693.  
  694.     subttl    --- Archive Description Record
  695.     page
  696.  
  697. inforec20:
  698.     call    prints            ; display record name
  699. inforec20a:
  700.     call    getc            ; get data length
  701.     mov    cl,al            ;  as whole word
  702.     call    getc            ;
  703.     mov    ch,al            ;
  704.     sub    cx,2            ; less length field
  705.     jle    arcvnext        ; no more
  706.  
  707.     call    getc            ; get record type code
  708.     mov    infocode,al        ;
  709.     sub    cx,1            ; less type field
  710.     jle    arcvnext        ; no more
  711.  
  712.     sub    bh,bh            ; get sub-type code
  713.     mov    bl,infocode        ;
  714.     shl    bx,1            ; get pointer to subtype name
  715.     lea    si,info20name[bx]    ;
  716.     lodsw                ;
  717.     mov    dx,ax            ;
  718.     call    prints            ; display info record name
  719. inforec20b:
  720.     call    getc            ; next data char
  721.     mov    dl,al            ;
  722.     mov    ah,2            ; write to stdout
  723.     int    21h            ;
  724.     loop    inforec20b        ;
  725.     jmp    arcvnext        ;
  726.  
  727.     subttl    --- Control records
  728.     page
  729.  
  730. controlrec:
  731.     jmp    inforec         ; check subtype codes
  732.  
  733. control30name    db    'Subdir  '
  734.  
  735. control30:                ; subdirectory entry
  736.     mov    si,offset control30name ;
  737.     mov    di,offset vstyle    ;
  738.     mov    cx,8            ;
  739.     rep    movsb            ;
  740.  
  741.     mov    si,offset vsize     ; format file size
  742.     mov    dx,archdr.mbrsize+2    ;
  743.     mov    ax,archdr.mbrsize    ;
  744.     test    options,z_parm        ; just this entry?
  745.     jnz    control30a        ; no, don't accumulate size
  746.     add    totsize,ax        ;
  747.     adc    totsize+2,dx        ;
  748. control30a:
  749.     call    format            ;
  750.  
  751.     mov    si,offset vlength    ; format file length
  752.     mov    dx,archdr.mbrlen+2    ;
  753.     mov    ax,archdr.mbrlen    ;
  754.     test    options,z_parm        ; just this entry?
  755.     jnz    control30b        ; no, don't accumulate lengths
  756.     add    totlen,ax        ;
  757.     adc    totlen+2,dx        ;
  758. control30b:
  759.     call    format            ;
  760.  
  761.     mov    ax,archdr.mbrdate    ; format file date
  762.     call    getdate         ;
  763.  
  764.     mov    ax,archdr.mbrtime    ; format file time
  765.     call    gettime         ;
  766.  
  767.     mov    ax,archdr.mbrcrc    ; format crc in hex
  768.     mov    di,offset vcrc        ;
  769.     call    cvh            ;
  770.  
  771.     print    vline            ; display this file info
  772.  
  773.     test    options,z_parm        ; want verbose subdir list?
  774.     jz    control30_exit        ; no, all done
  775.  
  776.     jmp    arcvnext        ; yes, pick up next header
  777.  
  778. control30_exit:
  779.     jmp    arcv_next        ; no, skip entire subdir
  780.  
  781.  
  782.     subttl    --- Miscellaneous subroutines
  783.     page
  784.  
  785. openarc proc    near            ; open new archive
  786.     push    bx            ;
  787.     mov    dx,offset arcname    ;
  788.     mov    ax,3d00h        ; for input
  789.     cmp    dosver,3        ; can we share?
  790.     jb    noshare         ;
  791.     or    al,40h            ; yes, deny none
  792. noshare:
  793.     int    21h            ; issue open
  794.     jc    openerr         ;
  795.     mov    archdl,ax        ; save file handle
  796.     clc                ;
  797.     pop    bx            ;
  798.     ret                ;
  799. openerr:
  800.     cmp    flags,0         ; find-first or open?
  801.     je    open_err        ;
  802.     jmp    nofiles         ;
  803. open_err:
  804.     printl    'Unable to open archive: '
  805.     print    arcname         ;
  806.     jmp    error            ;
  807. openarc endp
  808.  
  809.  
  810. closarc proc    near
  811.     push    bx            ;
  812.     mov    bx,archdl        ; previous handle
  813.     or    bx,bx            ; already open?
  814.     jz    closed            ;
  815.     mov    ah,3eh            ; yes, so close it
  816.     int    21h            ;
  817. closed: mov    archdl,0        ;
  818.     pop    bx            ;
  819.     ret                ;
  820. closarc endp
  821.  
  822.     page
  823. ;
  824. ;    print string like int 21h function 9
  825.  
  826. pause    db    cr,lf,'... more?$'
  827. backup    db    cr,9 dup (8),'$'
  828. linecnt db    0        ; line counter for pause
  829. pagecnt db    23        ; lines per screen
  830.  
  831. prints    proc    near            ; dx has offset to string
  832.  
  833.     test    options,p_parm        ; want pausing?
  834.     jz    ps1            ; no, skip next
  835.  
  836.     save    <bx,cx,dx,si>        ; save work regs
  837.     mov    al,linecnt        ;
  838.     cmp    al,pagecnt        ; end of screen?
  839.     jbe    ps0            ; not yet
  840.     mov    dx,offset pause     ; yup, say so
  841.     mov    ah,9            ;
  842.     int    21h            ;
  843.     mov    ah,0            ; get a key
  844.     int    16h            ;
  845.     mov    dx,offset backup    ; over write pause prompt
  846.     mov    ah,9            ;
  847.     int    21h            ;
  848.     mov    linecnt,0        ; reset line counter
  849. ps0:    restore <si,dx,cx,bx>        ; restore work regs
  850.  
  851. ps1:    save    <si,bx,cx>        ; save work regs
  852.     mov    si,dx            ;
  853.     sub    cx,cx            ;
  854. ps2:    lodsb                ;
  855.     cmp    al,stopper        ; ending hex ff?
  856.     je    ps8            ;
  857.     inc    cx            ; incr text length
  858.     cmp    al,lf            ; another line?
  859.     jne    ps2            ;
  860.     inc    linecnt         ;
  861.     jmp    ps2            ;
  862.  
  863. ps8:    mov    ah,40h            ; write to file
  864.     mov    bx,1            ; using std out
  865.     int    21h            ;
  866.  
  867. ps9:    restore <cx,bx,si>        ; recover registers
  868.     ret                ;
  869. prints    endp
  870.  
  871.     page
  872. ;
  873. ;    format the time
  874.  
  875. time    record    hour:5,min:6,sec:5    ; packed time
  876.  
  877. gettime proc    near            ; format the date
  878.     mov    di,offset vtime     ;
  879.     push    ax            ; save date
  880.     and    ax,mask hour        ; get hour part
  881.     mov    cl,hour         ; bits to shift
  882.     shr    ax,cl            ;
  883.     call    cnvrt1            ;
  884.     stosw                ;
  885.     mov    al,':'                  ;
  886.     stosb                ;
  887.  
  888. gt3:    pop    ax            ; get the time back
  889.     and    ax,mask min        ; get min part
  890.     mov    cl,min            ; bits to shift
  891.     call    cnvrt            ;
  892.     stosw
  893. gottime:ret
  894. gettime endp
  895.  
  896. cnvrt2    proc    near            ; convert to ascii
  897. cnvrt:    shr    ax,cl
  898. cnvrt1: aam                ; make al into bcd
  899.     or    ax,'00'                 ; and to ascii
  900.     xchg    al,ah            ;
  901. cnvrtd: ret                ;
  902. cnvrt2    endp
  903.  
  904.     page
  905. ;
  906. ;    format the date
  907.  
  908. date    record    yr:7,mo:4,dy:5        ; packed date
  909.  
  910. getdate proc    near            ; format the date
  911.     or    ax,ax            ; is it zero?
  912.     jz    gotdate         ;
  913.     push    ax            ; save date
  914.     and    ax,mask yr        ; get year part
  915.     mov    cl,yr            ; bits to shift
  916.     call    cnvrt            ;
  917.     mov    di,offset vyear     ;
  918.     or    al,'8'                  ; adjust for base year
  919.     stosw                ;
  920.  
  921.     pop    bx            ; get the date back
  922.     push    bx            ; save it
  923.     and    bx,mask mo        ; get month part
  924.     mov    cl,mo            ; bits to shift
  925.     shr    bx,cl            ;
  926.     add    bx,bx            ; form month table index
  927.     add    bx,bx            ;
  928.     lea    si,word ptr months-4[bx];
  929.     mov    cx,3            ;
  930.     mov    di,offset vmonth    ;
  931.     rep    movsb            ;
  932.  
  933.     pop    ax            ; get the date back
  934.     and    ax,mask dy        ; get day part
  935.     mov    cl,dy            ; bits to shift
  936.     call    cnvrt            ;
  937.     mov    di,offset vdate     ;
  938.     stosw                ;
  939. gotdate:ret                ;
  940. getdate endp
  941.  
  942.     page
  943. ;
  944. ;     format 4-byte binary into ASCII for display
  945.  
  946. ddptr    dw    0            ;
  947.  
  948. format    proc    near            ; formats a 32 bit integer in dx:ax
  949.     save    <bp,bx,di,si>        ;  to ds:si
  950.     mov    ddptr,si        ; addr of target field
  951.     mov    di,dx            ; routine uses di:si
  952.     mov    si,ax            ;
  953.     call    printdd         ;
  954.     restore <si,di,bx,bp>        ;
  955.     ret                ;
  956.  
  957. printdd:
  958.     xor    ax,ax            ; zero out the
  959.     mov    bx,ax            ; working
  960.     mov    bp,ax            ; registers.
  961.     mov    cx,32            ; # bits of precision
  962. j1:    shl    si,1            ;
  963.     rcl    di,1            ;
  964.     xchg    bp,ax            ;
  965.     call    j6            ;
  966.     xchg    bp,ax            ;
  967.     xchg    bx,ax            ;
  968.     call    j6            ;
  969.     xchg    bx,ax            ;
  970.     adc    al,0            ;
  971.     loop    j1            ;
  972.     mov    cx,1710h        ;
  973.     mov    ax,bx            ;
  974.     call    j2            ;
  975.     mov    ax,bp            ;
  976. j2:    push    ax            ;
  977.     mov    dl,ah            ;
  978.     call    j3            ;
  979.     pop    dx            ;
  980. j3:    mov    dh,dl            ;
  981.     shr    dl,1            ; move high
  982.     shr    dl,1            ;  nibble to
  983.     shr    dl,1            ;   the low
  984.     shr    dl,1            ;    position
  985.     call    j4            ;
  986.     mov    dl,dh            ;
  987. j4:    and    dl,0fh            ; mask low nibble
  988.     jz    j5            ; if not zero
  989.     mov    cl,0            ;
  990. j5:    dec    ch            ;
  991.     and    cl,ch            ;
  992.     or    dl,'0'                  ; fold in ascii zero
  993.     sub    dl,cl            ;
  994.     mov    bx,ddptr        ;
  995.     mov    [bx],dl         ; ptr to next target field
  996.     inc    ddptr            ;
  997.     ret                ;
  998.  
  999. j6:    adc    al,al            ;
  1000.     daa                ;
  1001.     xchg    al,ah            ;
  1002.     adc    al,al            ;
  1003.     daa                ;
  1004.     xchg    al,ah            ;
  1005.     ret                ;
  1006. format    endp
  1007.  
  1008.     page
  1009. cvh    proc    near            ; convert 16-bit binary word in ax
  1010.     save    <di,bx,cx,dx>        ; to hex ASCII string at ds:di
  1011.  
  1012.     mov    dx,ax            ; save 16-bits
  1013.  
  1014.     mov    bl,dh            ; third nibble
  1015.     mov    cl,4            ;
  1016.     shr    bl,cl            ;
  1017.     mov    al,hexchar[bx]        ;
  1018.     stosb                ;
  1019.  
  1020.     mov    bl,dh            ; last nibble
  1021.     and    bl,0fh            ;
  1022.     mov    al,hexchar[bx]        ;
  1023.     stosb                ;
  1024.  
  1025.     mov    bl,dl            ; first nibble
  1026.     mov    cl,4            ;
  1027.     sub    bh,bh            ;
  1028.     shr    bl,cl            ; isolate
  1029.     mov    al,hexchar[bx]        ;
  1030.     stosb                ;
  1031.  
  1032.     mov    bl,dl            ; second nibble
  1033.     and    bl,0fh            ; isolate
  1034.     mov    al,hexchar[bx]        ;
  1035.     stosb                ;
  1036.     restore <dx,cx,bx,di>        ; restore registers
  1037.     ret                ; return
  1038.  
  1039. hexchar db    '0123456789ABCDEF'      ; for conversion
  1040. cvh    endp
  1041.  
  1042.     subttl    ' - i/o subroutines'
  1043.     page
  1044.  
  1045. getc    proc    near            ; return next byte in al
  1046.     push    si            ;  or cf=1 for eof
  1047. getc1:
  1048.     dec    inlen            ; any left in buffer
  1049.     jl    getc2            ; yes, pick it up
  1050.     mov    si,inptr        ; offset to next byte
  1051.     lodsb                ;
  1052.     mov    inptr,si        ;
  1053.     pop    si            ;
  1054.     clc                ;
  1055.     ret                ;
  1056. getc2:
  1057.     call    getblk            ; read next block
  1058.     jnc    getc1            ;
  1059.     pop    si            ; return cf=1 at eof
  1060.     ret                ;
  1061. getc    endp
  1062.  
  1063.  
  1064. getblk    proc    near            ; read next block
  1065.     save    <bx,cx,dx>        ;
  1066.     mov    ah,3fh            ; read from handle
  1067.     mov    bx,archdl        ; arc file handle
  1068.     mov    cx,inbufsz        ; input buffer size
  1069.     mov    dx,offset inbuf     ; offset to input buffer
  1070.     mov    inptr,dx        ;
  1071.     int    21h            ;
  1072.     jc    getblkr         ; oops
  1073.     or    ax,ax            ; anything read?
  1074.     jnz    getblka         ;
  1075.     stc                ; no, set cf=1 for eof
  1076.     jmp    getblkx         ; and exit
  1077. getblka:
  1078.     mov    inlen,ax        ; return count of bytes read
  1079. getblkx:
  1080.     restore <dx,cx,bx>        ;
  1081.     ret                ;
  1082.  
  1083. getblkr:
  1084.     printl    'I/O error reading '    ;
  1085.     print    arcname         ;
  1086.     jmp    error            ; gotta quit
  1087. getblk    endp
  1088.  
  1089.     subttl    '--- load next archive header'
  1090.     page
  1091.  
  1092. gethdr    proc    near
  1093.     call    getc            ; get next file byte
  1094.     jc    gethdrr1        ; premature eof?
  1095.     cmp    al,arcmark        ; start of header?
  1096.     je    gethdr3         ; yup, let's start cookin
  1097.     jmp    gethdr            ; look through the whole file
  1098.  
  1099. gethdr3:
  1100.     mov    dx,1            ; length of header so far
  1101.     call    getc            ; get version code
  1102. ;;    jc    gethdrr3        ;
  1103.     jnc    gethdr3a        ;
  1104.     jmp    gethdrr3        ;
  1105.  
  1106. gethdr3a:
  1107.     inc    dx            ; accumulate header length
  1108.     mov    archdr.mbrcode,al    ;
  1109.  
  1110.     cmp    al,arcver        ; reasonable code?
  1111. ;;    ja    gethdrr3        ; nope, funny stuff
  1112.     jbe    gethdr3b
  1113.     jmp    gethdrr3        ;
  1114.  
  1115. gethdr3b:
  1116.     cmp    al,0            ; archive eof?
  1117.     je    gethdr9         ; yup done
  1118.     cmp    al,31            ; end of subdir entry?
  1119.     je    gethdr9         ; yup, not much to it
  1120.  
  1121.     mov    cx,13            ; get member name
  1122.     mov    di,offset archdr.mbrname
  1123. gethdr4:
  1124.     call    getc            ;
  1125.     jc    gethdrr1        ;
  1126.     inc    dx            ; accumulate header length
  1127.     stosb                ;
  1128.     loop    gethdr4         ;
  1129. gethdr5:
  1130.     mov    cx,10            ; length remaining
  1131.     cmp    archdr.mbrcode,1    ; old format?
  1132.     je    gethdr6         ; yes, it's short
  1133.     mov    cl,14            ;
  1134. gethdr6:
  1135.     mov    di,offset archdr.mbrsize
  1136. gethdr7:
  1137.     call    getc            ;
  1138.     jc    gethdrr1        ;
  1139.     inc    dx            ; accumulate header length
  1140.     stosb                ;
  1141.     loop    gethdr7         ;
  1142. gethdr8:
  1143.     cmp    archdr.mbrcode,1    ; old format?
  1144.     jne    gethdr9         ; if so, it's short
  1145.     mov    si,offset mbrsize    ;
  1146.     mov    di,offset mbrlen    ;
  1147.     mov    cx,4            ;
  1148.     rep    movsb            ;
  1149. gethdr9:
  1150.     cmp    archdr.mbrcode,20    ; info record?
  1151.     jne    gethdr10        ; yes, have enough
  1152. gethdr10:
  1153.     add    totsize,dx        ; include header size
  1154.     adc    totsize+2,0        ;  in compressed file sizes
  1155.     clc                ; return cf=0
  1156.     ret                ;
  1157.  
  1158.     page
  1159.     subttl    --- Get Header error messages
  1160.  
  1161. gethdrr1:
  1162.     printl    'Invalid archive: archive header not found!'
  1163.     jmp    error            ;
  1164.  
  1165. gethdrr2:
  1166.     printl    'Invalid archive:  premature end of file!'
  1167.     jmp    error            ;
  1168.  
  1169. gethdrr3:
  1170.     printl    'Invalid archive:  header code invalid!'
  1171.     jmp    error
  1172.  
  1173.  
  1174. ;    ----  Error messages
  1175.  
  1176. vermsg    db    cr,lf,'Wrong DOS version',cr,lf,stopper
  1177.  
  1178. hdrmsg    db    cr,lf,'Invalid archive header: Type '
  1179. hdrcode db    '  .',stopper
  1180.  
  1181. gethdr    endp
  1182.  
  1183.     subttl    '--- i/o data areas'
  1184.     page
  1185.  
  1186. arcv    endp
  1187.  
  1188.         even
  1189. dta        equ    $        ; data transfer area
  1190.  
  1191. archdr        equ    dta + 48    ; i/o area for a header
  1192.  
  1193. inbuf        equ    archdr + 64    ; read i/o buffer
  1194.  
  1195. cseg    ends
  1196.     end    arcv
  1197.